//****************************************/
//* mElements  12 2011                   */
//* Riku Maikola rpm@ac-mapa.org         */
//****************************************/

#include "../mElements.h"

mPoint eArc::p1()
{
    return at(0);
};
mPoint eArc::p2()
{
    return at(1);
};
mPoint eArc::cp()
{
    return at(2);
};


//********************************************************************************************************//
//**                //\\    element boxing  13.12.2012
//**               //__\\
//**              //    \\
//********************************************************************************************************//
void eArc::cArea()
{
    ClearArea();

    while(a1>TAU)
    {
        a1=a1-TAU;
    }
    while(a2>TAU)
    {
        a2=a2-TAU;
    }

    test(p1());
    test(p2());

    if(IsInArc(a1,a2,PI))       L.x = cp().x-r;
    if(IsInArc(a1,a2,0))        H.x = cp().x+r;
    if(IsInArc(a1,a2,PI/2))     H.y = cp().y+r;
    if(IsInArc(a1,a2,TAU*0.75)) L.y = cp().y-r;
}
//***********************************************************************************//
//**                                                                               **//
//**          get readbl data                         18.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//

//***********************************************************************************//
bool eArc::Match(eArc ci)
{
    if( cp().Match(ci.cp()) && AER(r,ci.r) && p1().Match(ci.p1()) && p2().Match(ci.p2())  )return true;
    return false;
}

//***********************************************************************************//
//**                                                                               **//
//**          get readbl data                         18.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
wxString eArc::Info()
{
    return wxString::Format( _("arc cp()(%1.3f,%1.3f) a(%1.3f,%1.3f) r(%f)"),cp().x,cp().y,a1,a2,r);
}

//***********************************************************************************//
//**                                                                               **//
//**          Connection  jump                       13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
bool eArc::Connection(mPoint *point,mPoint *center,int *type)
{
    if(p1().Match(*point))
    {
        point->SetValue(p2());
        center->SetValue(cp());
        *type = 173;
        return true;
    }
    if(p2().Match(*point))
    {
        point->SetValue(p1());
        center->SetValue(cp());
        *type = 172;
        return true;
    }
    return false;
}
//***********************************************************************************//
//**                                                                               **//
//**          get Distance from xy location          13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
double eArc::Distance(double X,double Y)
{
    mPoint mp(X,Y,0);
    double angle = cp().GetDirectionXY(mp);
    double d=100000000000000,d2,d3;
    if(IsInArc(a1,a2,angle))
    {
        d = r-cp().GetDistanceXY(mp);
        if(d<0)d=-d;
    }
    d2 = mp.GetDistanceXY(p1());
    d3 = mp.GetDistanceXY(p2());

    if(d2<d)d=d2;
    if(d3<d)d=d3;

    return d;
}
//***********************************************************************************//
//**                                                                               **//
//**          get cirle area collison points         13.12.2012                    **//
//**                                                                               **//
//***********************************************************************************//
bool eArc::Intersection(mPointArray *A,eLine line)
{
    mPointArray p;
    bool answer=false;
    if(line.Intersection(&p, eC(mP(cp().x,cp().y,0),r)))
    {
        for(uint a=0; a<p.size(); a++)
        {
            if(Distance(p.at(a).x , p.at(a).y )<0.0000001)
            {
                A->Add(p.at(a),true);
                answer = true;
            }
        }
    }
    return answer;
}
bool eArc::Intersection(mPointArray *A,eArc arc)
{

    mPointArray p;
    bool answer = false;
    if(Intersection(&p,eC(arc.cp(),arc.r)))
    {
        for(uint a=0;a<p.size();a++)
        {
            if(arc.Distance(p.at(a).x , p.at(a).y )<0.000001)
            {
                A->Add(p.at(a),true);
                answer = true;
            }
        }
    }
    return answer;
}
//******************** eArc    **************************************//
bool eArc::Intersection(mPointArray *A,eCircle cir)
{
    uint size = A->size();
    double d=cp().GetDistanceXY(cir.cp());
    double dx=((d*d)-(cir.r*cir.r)+(r*r))/(d*2);
    double dy=sqrt((r*r)-(dx*dx));

    if(dx>r || (-dx)>r)return false;

    double da = cp().GetDirectionXY(cir.cp());

    mPoint mp,t1,t2;
    mp = cp().GetFromPoint(da,dx);

    t1 = mp.GetFromPoint(da+1.570796325,dy);
    t2 = mp.GetFromPoint(da-1.570796325,dy);

    if(Distance(t1.x,t1.y)<0.000001) A->Add(t1,true);
    if(Distance(t2.x,t2.y)<0.000001) A->Add(t2,true);

    if(size<A->size())return true;
    return false;
}

bool eArc::Intersection(mPointArray *A,eRay ray)
{
    mPointArray p;
    bool answer = false;
    if( eC(mP(cp().x,cp().y,0),r).Intersection(&p,ray))
    {
        for(uint a=0; a<p.size(); a++)
        {
            if(Distance(p.at(a).x,p.at(a).y)<0.0000001)
            {
                A->Add(p.at(a),true);
                answer=true;
            }
        }
    }
    return answer;
}
//***************************//
//**
//**
//**
//***************************//
mPoint eArc::MidPoint()
{
    double alfa=a2;
    if(a2<a1)
    {
        alfa+=TAU;
    }
    alfa = a1 + ( alfa-a1 )/2;
    return cp().GetFromPoint(alfa,r);
};
//************************************************************************************************//
//**                                                                                            **//
//**                        ToArray                                                             **//
//**                                                                                            **//
//************************************************************************************************//

mPointArray eArc::ToArray(double accuracy)
{
    mPointArray P;

    if(a1>a2)a2+=TAU;
    double am=TAU;
    if(r>accuracy)
        am = acos((r-accuracy)/r)*2;


    if(direction)
    {
        P.Add(p1(),true);
        for(double a3=a1; a3<a2; a3=a3+am)
        {
            P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
            P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
        }
        P.Add(p2());
    }
    else
    {
        P.Add(p2(),true);
        for(double a3=a2; a3>a1; a3=a3-am)
        {
            P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
            P.Add(mP(cp().x+cos(a3)*r,cp().y+sin(a3)*r,0));
        }
        P.Add(p1());
    }


    return P;

}
//*************************************//
bool eArc::Split(Image*I,mPoint point)
{
    if( Distance(point.x,point.y)>0.00001)
    {
        return false;
    }
    if(point.Match(p1()))return false;
    if(point.Match(p2()))return false;

    double a3 = cp().GetDirectionXY(point);

    I->add(eA(cp(),a1,a3,r));
    a1=a3;
    p1()= mP( cos(a3)*r+cp().x,sin(a3)*r+cp().y);

    return true;
}



//************************************************************************************************//
//**                                                                                            **//
//**                        GLOBAL..                                                            **//
//**                                                                                            **//
//************************************************************************************************//
eArc eA(mPoint cp , double a1,double a2,double r,wxString L)
{
    eArc arc;
//    arc.layer=L;
    arc.r = r;
    arc.a1 = a1;
    arc.a2 = a2;
    arc.flag = false;
    arc.push_back( mP(cos(a1)*r+cp.x,sin(a1)*r+cp.y));
    arc.push_back( mP(cos(a2)*r+cp.x,sin(a2)*r+cp.y) );
    arc.push_back( mP(cp.x,cp.y));

    arc.cArea();
    return arc;
}

eArc eA(mPoint p1 , mPoint p2 , double r,wxString L)
{


    mPoint cp;
    cp.SetCCWCircleCenter(p1,p2,r);
    if(r<0)r=-r;

    eArc arc;
//    arc.layer=L;
    arc.r = r;
    arc.a1 = cp.GetDirectionXY(p1);
    arc.a2 = cp.GetDirectionXY(p2);
    arc.flag = false;
    arc.push_back( mP( cos(arc.a1)*r+cp.x,sin(arc.a1)*r+cp.y) );
    arc.push_back( mP( cos(arc.a2)*r+cp.x,sin(arc.a2)*r+cp.y) );
    arc.push_back( mP( cp.x,cp.y));

    arc.cArea();
    return arc;
}
